﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace StyleMVVM.Utilities
{
	public class WeakAction
	{
		private readonly Action<object> executeAction;
		private readonly WeakReference reference;

		public WeakAction(Action action)
		{
			if (action.Target != null)
			{
				reference = new WeakReference(action.Target);

				MethodInfo methInfo = action.GetMethodInfo();

				ParameterExpression param = Expression.Parameter(typeof(object), "target");

				UnaryExpression cast =
					Expression.ConvertChecked(param, action.Target.GetType());

				Expression call = Expression.Call(cast, methInfo);

				executeAction =
					Expression.Lambda<Action<object>>(call, param).Compile();
			}
			else
			{
				throw new ArgumentNullException("Action.Target can not be null");
			}
		}

		public bool IsAlive
		{
			get { return reference.IsAlive; }
		}

		public void Execute()
		{
			object target = reference.Target;

			if (executeAction != null && target != null)
			{
				executeAction(target);
			}
		}
	}
}